<template>
  <div class="audio-recorder-modal" v-if="show" @click.self="close">
    <div class="recorder-dialog" @click.stop>
      <div class="dialog-header">
        <h3>🎤 录音</h3>
        <button class="close-btn" @click="close">×</button>
      </div>
      
      <div class="recorder-content">
        <!-- 录音状态显示 -->
        <div class="recorder-status">
          <div v-if="!isRecording && !recordedAudio" class="status-idle">
            <p>点击下方按钮开始录音</p>
          </div>
          
          <div v-if="isRecording" class="status-recording">
            <div class="recording-indicator">
              <span class="pulse-dot"></span>
              <span>正在录音中...</span>
            </div>
            <div class="recording-time">{{ formatTime(recordingTime) }}</div>
          </div>
          
          <div v-if="recordedAudio && !isRecording" class="status-recorded">
            <audio :src="recordedAudioUrl" controls class="audio-player"></audio>
            <div class="audio-info">
              <span>时长: {{ formatTime(recordingDuration) }}</span>
              <span>大小: {{ formatFileSize(recordingSize) }}</span>
            </div>
          </div>
        </div>
        
        <!-- 录音控制按钮 -->
        <div class="recorder-controls">
          <button 
            v-if="!isRecording && !recordedAudio" 
            class="btn-record" 
            @click="startRecording"
            :disabled="!canRecord"
          >
            🎤 开始录音
          </button>
          
          <button 
            v-if="isRecording" 
            class="btn-stop" 
            @click="stopRecording"
          >
            ⏹️ 停止录音
          </button>
          
          <button 
            v-if="recordedAudio && !isRecording" 
            class="btn-rerecord" 
            @click="rerecord"
          >
            🔄 重新录音
          </button>
        </div>
        
        <!-- 错误提示 -->
        <div v-if="error" class="error-message">
          {{ error }}
        </div>
        
        <!-- 上传进度 -->
        <div v-if="uploading" class="upload-progress">
          <div class="progress-bar">
            <div class="progress-fill" :style="{ width: uploadProgress + '%' }"></div>
          </div>
          <div class="progress-text">上传中: {{ uploadProgress.toFixed(1) }}%</div>
        </div>
      </div>
      
      <div class="dialog-footer">
        <button class="btn-cancel" @click="close">取消</button>
        <button 
          class="btn-confirm" 
          @click="confirm"
          :disabled="!recordedAudio || uploading"
        >
          {{ uploading ? '上传中...' : '确认插入' }}
        </button>
      </div>
    </div>
  </div>
</template>

<script>
import { childEnglishApi } from '@/api/childEnglishApi';

export default {
  name: 'AudioRecorder',
  props: {
    show: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      isRecording: false,
      recordedAudio: null,
      recordedAudioUrl: null,
      recordingTime: 0,
      recordingDuration: 0,
      recordingSize: 0,
      mediaRecorder: null,
      audioChunks: [],
      timer: null,
      error: null,
      uploading: false,
      uploadProgress: 0,
      canRecord: false
    };
  },
  mounted() {
    this.checkRecordingSupport();
  },
  methods: {
    async checkRecordingSupport() {
      // 检查浏览器是否支持MediaRecorder API
      if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
        this.canRecord = false;
        this.error = '浏览器不支持录音功能，请使用Chrome、Firefox或Edge浏览器';
        return;
      }

      // 检查是否在HTTPS环境下（localhost除外）
      if (location.protocol !== 'https:' && location.hostname !== 'localhost' && location.hostname !== '127.0.0.1') {
        this.canRecord = false;
        this.error = '录音功能需要在HTTPS环境下使用，请使用HTTPS访问或使用localhost';
        return;
      }

      try {
        // 尝试获取麦克风权限（但不立即停止，让用户点击时再请求）
        // 这里只检查API是否可用，不实际请求权限
        if (typeof MediaRecorder === 'undefined') {
          this.canRecord = false;
          this.error = '浏览器不支持MediaRecorder API，请使用Chrome、Firefox或Edge浏览器';
          return;
        }

        // 检查是否有支持的MIME类型
        const hasSupportedMimeType = this.getSupportedMimeType();
        if (!hasSupportedMimeType) {
          this.canRecord = false;
          this.error = '浏览器不支持音频录制格式，请使用Chrome、Firefox或Edge浏览器';
          return;
        }

        // API支持，允许录音（实际权限在用户点击时请求）
        this.canRecord = true;
        this.error = null;
      } catch (error) {
        this.canRecord = false;
        console.error('录音支持检查失败:', error);
        this.error = '无法检查录音支持，请确保浏览器支持录音功能';
      }
    },
    
    async startRecording() {
      try {
        this.error = null;
        
        // 再次检查API支持
        if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
          this.error = '浏览器不支持录音功能，请使用Chrome、Firefox或Edge浏览器';
          return;
        }

        const stream = await navigator.mediaDevices.getUserMedia({ 
          audio: {
            echoCancellation: true,
            noiseSuppression: true,
            autoGainControl: true
          }
        });
        
        this.audioChunks = [];
        const mimeType = this.getSupportedMimeType();
        this.mediaRecorder = new MediaRecorder(stream, {
          mimeType: mimeType
        });
        
        this.mediaRecorder.ondataavailable = (event) => {
          if (event.data.size > 0) {
            this.audioChunks.push(event.data);
          }
        };
        
        this.mediaRecorder.onstop = () => {
          const audioBlob = new Blob(this.audioChunks, { 
            type: this.mediaRecorder.mimeType 
          });
          this.recordedAudio = audioBlob;
          this.recordedAudioUrl = URL.createObjectURL(audioBlob);
          this.recordingDuration = this.recordingTime;
          this.recordingSize = audioBlob.size;
          
          // 停止所有音频轨道
          stream.getTracks().forEach(track => track.stop());
        };
        
        this.mediaRecorder.start();
        this.isRecording = true;
        this.recordingTime = 0;
        this.canRecord = true; // 成功启动后标记为可用
        
        // 开始计时
        this.timer = setInterval(() => {
          this.recordingTime++;
          // 限制最长录音时间为5分钟
          if (this.recordingTime >= 300) {
            this.stopRecording();
          }
        }, 1000);
        
      } catch (error) {
        this.canRecord = false;
        console.error('录音启动失败:', error);
        
        // 根据错误类型提供更详细的错误信息
        if (error.name === 'NotAllowedError' || error.name === 'PermissionDeniedError') {
          this.error = '麦克风权限被拒绝，请在浏览器设置中允许访问麦克风';
        } else if (error.name === 'NotFoundError' || error.name === 'DevicesNotFoundError') {
          this.error = '未找到麦克风设备，请检查设备连接';
        } else if (error.name === 'NotReadableError' || error.name === 'TrackStartError') {
          this.error = '麦克风被其他应用占用，请关闭其他使用麦克风的应用';
        } else if (error.name === 'OverconstrainedError' || error.name === 'ConstraintNotSatisfiedError') {
          this.error = '麦克风不支持所需的音频设置';
        } else if (error.name === 'NotSupportedError') {
          this.error = '浏览器不支持录音功能，请使用Chrome、Firefox或Edge浏览器';
        } else {
          this.error = `无法访问麦克风: ${error.message || '未知错误'}，请检查浏览器权限设置`;
        }
      }
    },
    
    stopRecording() {
      if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
        this.mediaRecorder.stop();
        this.isRecording = false;
        if (this.timer) {
          clearInterval(this.timer);
          this.timer = null;
        }
      }
    },
    
    rerecord() {
      this.recordedAudio = null;
      this.recordedAudioUrl = null;
      this.recordingTime = 0;
      this.recordingDuration = 0;
      this.recordingSize = 0;
      if (this.recordedAudioUrl) {
        URL.revokeObjectURL(this.recordedAudioUrl);
        this.recordedAudioUrl = null;
      }
    },
    
    async confirm() {
      if (!this.recordedAudio) {
        return;
      }
      
      try {
        this.uploading = true;
        this.uploadProgress = 0;
        this.error = null;
        
        // 创建FormData
        const formData = new FormData();
        const fileName = `voice_${Date.now()}.webm`;
        formData.append('audio', this.recordedAudio, fileName);
        
        // 上传音频文件
        const response = await this.uploadAudio(formData);
        
        if (response && response.code === 200) {
          // 触发插入事件，传递音频URL和相关信息
          this.$emit('insert', {
            url: response.data.url || response.data.fileUrl,
            duration: this.recordingDuration,
            size: this.recordingSize,
            fileName: fileName
          });
          
          this.close();
        } else {
          this.error = response?.message || '上传失败，请重试';
        }
      } catch (error) {
        this.error = '上传失败: ' + (error.message || '未知错误');
        console.error('音频上传失败:', error);
      } finally {
        this.uploading = false;
      }
    },
    
    async uploadAudio(formData) {
      try {
        // 使用axios上传，支持进度监控
        const axios = (await import('axios')).default;
        const token = sessionStorage.getItem('token');
        const csrfToken = localStorage.getItem('csrfToken');
        
        // 构建请求头
        const headers = {
          'Content-Type': 'multipart/form-data'
        };
        
        if (token) {
          headers['Authorization'] = `Bearer ${token}`;
        }
        
        if (csrfToken) {
          headers['X-CSRF-TOKEN'] = csrfToken;
        }
        
        const response = await axios.post(
          `${childEnglishApi.getCurrentServer()}/api/guidance/upload-audio`,
          formData,
          {
            headers: headers,
            withCredentials: true, // 重要：支持CORS和Session
            timeout: 60000, // 60秒超时，大文件上传需要更长时间
            onUploadProgress: (progressEvent) => {
              if (progressEvent.total) {
                this.uploadProgress = (progressEvent.loaded / progressEvent.total) * 100;
              }
            }
          }
        );
        
        // 从响应头获取CSRF Token
        const newCsrfToken = response.headers['x-csrf-token'];
        if (newCsrfToken) {
          localStorage.setItem('csrfToken', newCsrfToken);
        }
        
        return response.data;
      } catch (error) {
        // 处理错误，提供更详细的错误信息
        if (error.response) {
          // 服务器返回了错误响应
          throw new Error(error.response.data?.message || `服务器错误: ${error.response.status}`);
        } else if (error.request) {
          // 请求已发出但没有收到响应
          throw new Error('网络错误：无法连接到服务器，请检查后端服务是否运行');
        } else {
          // 其他错误
          throw new Error(error.message || '上传失败');
        }
      }
    },
    
    getSupportedMimeType() {
      const types = [
        'audio/webm;codecs=opus',
        'audio/webm',
        'audio/ogg;codecs=opus',
        'audio/mp4',
        'audio/wav'
      ];
      
      for (const type of types) {
        if (MediaRecorder.isTypeSupported(type)) {
          return type;
        }
      }
      return 'audio/webm'; // 默认
    },
    
    formatTime(seconds) {
      const mins = Math.floor(seconds / 60);
      const secs = seconds % 60;
      return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
    },
    
    formatFileSize(bytes) {
      if (bytes === 0) return '0 B';
      const k = 1024;
      const sizes = ['B', 'KB', 'MB', 'GB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
    },
    
    close() {
      if (this.isRecording) {
        this.stopRecording();
      }
      if (this.recordedAudioUrl) {
        URL.revokeObjectURL(this.recordedAudioUrl);
      }
      this.$emit('close');
      // 重置状态
      this.recordedAudio = null;
      this.recordedAudioUrl = null;
      this.recordingTime = 0;
      this.recordingDuration = 0;
      this.recordingSize = 0;
      this.error = null;
      this.uploading = false;
      this.uploadProgress = 0;
    }
  },
  
  beforeUnmount() {
    if (this.timer) {
      clearInterval(this.timer);
    }
    if (this.recordedAudioUrl) {
      URL.revokeObjectURL(this.recordedAudioUrl);
    }
    if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
      this.mediaRecorder.stop();
    }
  }
};
</script>

<style scoped>
.audio-recorder-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.recorder-dialog {
  background: white;
  border-radius: 12px;
  width: 90%;
  max-width: 500px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}

.dialog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  border-bottom: 1px solid #e0e0e0;
}

.dialog-header h3 {
  margin: 0;
  color: #2c3e50;
}

.close-btn {
  background: none;
  border: none;
  font-size: 28px;
  color: #7f8c8d;
  cursor: pointer;
  padding: 0;
  width: 30px;
  height: 30px;
  line-height: 30px;
  transition: color 0.3s;
}

.close-btn:hover {
  color: #e74c3c;
}

.recorder-content {
  padding: 20px;
}

.recorder-status {
  min-height: 150px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin-bottom: 20px;
}

.status-idle {
  text-align: center;
  color: #7f8c8d;
}

.status-recording {
  text-align: center;
}

.recording-indicator {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-bottom: 10px;
  color: #e74c3c;
  font-weight: bold;
}

.pulse-dot {
  width: 12px;
  height: 12px;
  background: #e74c3c;
  border-radius: 50%;
  animation: pulse 1.5s infinite;
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.5;
    transform: scale(1.2);
  }
}

.recording-time {
  font-size: 24px;
  font-weight: bold;
  color: #2c3e50;
  font-family: 'Courier New', monospace;
}

.status-recorded {
  width: 100%;
}

.audio-player {
  width: 100%;
  margin-bottom: 10px;
}

.audio-info {
  display: flex;
  justify-content: space-around;
  font-size: 14px;
  color: #7f8c8d;
}

.recorder-controls {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-bottom: 20px;
}

.btn-record,
.btn-stop,
.btn-rerecord {
  padding: 12px 24px;
  border: none;
  border-radius: 8px;
  font-size: 16px;
  font-weight: bold;
  cursor: pointer;
  transition: all 0.3s;
}

.btn-record {
  background: #3498db;
  color: white;
}

.btn-record:hover:not(:disabled) {
  background: #2980b9;
}

.btn-record:disabled {
  background: #bdc3c7;
  cursor: not-allowed;
}

.btn-stop {
  background: #e74c3c;
  color: white;
}

.btn-stop:hover {
  background: #c0392b;
}

.btn-rerecord {
  background: #f39c12;
  color: white;
}

.btn-rerecord:hover {
  background: #e67e22;
}

.error-message {
  background: #fee;
  color: #c33;
  padding: 10px;
  border-radius: 6px;
  margin-bottom: 10px;
  font-size: 14px;
}

.upload-progress {
  margin-top: 10px;
}

.progress-bar {
  width: 100%;
  height: 8px;
  background: #ecf0f1;
  border-radius: 4px;
  overflow: hidden;
  margin-bottom: 5px;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #3498db, #2ecc71);
  transition: width 0.3s;
}

.progress-text {
  text-align: center;
  font-size: 12px;
  color: #7f8c8d;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 20px;
  border-top: 1px solid #e0e0e0;
}

.btn-cancel,
.btn-confirm {
  padding: 10px 20px;
  border: none;
  border-radius: 6px;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.3s;
}

.btn-cancel {
  background: #ecf0f1;
  color: #2c3e50;
}

.btn-cancel:hover {
  background: #bdc3c7;
}

.btn-confirm {
  background: #3498db;
  color: white;
}

.btn-confirm:hover:not(:disabled) {
  background: #2980b9;
}

.btn-confirm:disabled {
  background: #bdc3c7;
  cursor: not-allowed;
}
</style>

